package com.vhall.component.service.inav.impl;

import com.alibaba.fastjson.JSONObject;
import com.vhall.component.entity.inav.vo.InviteReqVO;
import com.vhall.component.entity.room.dto.RoomJoinsEntityDTO;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.constant.RoomConstant;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.VssToken;
import com.vhall.component.service.inav.InviteService;
import com.vhall.component.service.inav.WheatCacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 直播间邀请上麦
 *
 * @author yongzheng.xu
 * @date 2021/6/23 20:37
 */
@Slf4j
@Service
public class InviteServiceImpl extends BaseService implements InviteService {

    @Autowired
    private WheatCacheService wheatCacheService;

    @Override
    public Boolean invite(InviteReqVO reqVO, VssToken token) {
        log.info("invite方法开始：参数为{}", reqVO);
        String roomId = reqVO.getRoomId();
        Integer receiverId = reqVO.getReceiveAccountId();
        //获取当前直播间的主持人
        RoomJoinsEntityDTO host = roomInnerService.getCurrentJoinUserByThirdId(roomId, token.getThirdPartyUserId());
        //角色非主持人则无操作权限
        if (!host.getRoleName().equals(RoomConstant.HOST)) {
            //无操作权限
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        //获取房间信息
        RoomsEntityDTO room = roomInnerService.getRoomInfo(roomId);
        if (null == room) {
            //空房间
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        if (room.getStatus() != 1) {
            //房间直播状态错误
            throw new BusinessException(BizErrorCode.BIZ_NOT_START);
        }
        //获取被邀请的成员的参会信息
        RoomJoinsEntityDTO joiner = roomInnerService.getRoomJoinInfo(receiverId, roomId);
        if (null == joiner) {
            return false;
        }
        if (!joiner.getRoleName().equals(RoomConstant.INTERACTION) && !joiner.getRoleName().equals(RoomConstant.ASSISTANT)
                && !joiner.getRoleName().equals(RoomConstant.AUDIENCE)) {
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        //获取邀请列表(key为成员id value为邀请剩余时间)
        Map<String, Long> invities = getInviteList(roomId);
        if (invities.containsKey(joiner.getAccountId().toString())) {
            throw new BusinessException(BizErrorCode.BIZ_REPEAT_INVITATION);
        }
        sendInvite(joiner, roomId, room.getChannelId());
        // 缓存上麦中
        wheatCacheService.cacheWaitingForWheat(roomId, joiner.getAccountId());
        return true;
    }


    @Override
    public Boolean rejectInvite(RoomsEntityDTO room, VssToken token, InviteReqVO reqVO) {
        String roomId = reqVO.getRoomId();
        Integer thirdId = token.getThirdPartyUserId();
        //获取参会成员信息
        RoomJoinsEntityDTO joiner = roomInnerService.getCurrentJoinUserByThirdId(roomId, thirdId);
        //获取邀请中的列表(key为用户id value为过期时间)
        Map<String, Long> inviters = getInviteList(roomId);
        if (null == joiner) {
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        if (!inviters.containsKey(joiner.getAccountId().toString())) {
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        //回复邀请(paas发送消息)
        replyInvite(joiner, 0, room.getChannelId());
        return true;
    }

    @Override
    public Boolean agreeInvite(RoomsEntityDTO room, VssToken token, InviteReqVO reqVO) {
        String roomId = reqVO.getRoomId();
        Integer thirdId = token.getThirdPartyUserId();
        //获取参会成员信息
        RoomJoinsEntityDTO joiner = roomInnerService.getCurrentJoinUserByThirdId(roomId, thirdId);
        //获取邀请列表(key为用户id value为过期时间)
        Map<String, Long> inviters = getInviteList(roomId);
        if (null == joiner) {
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        if (!inviters.containsKey(joiner.getAccountId().toString())) {
            throw new BusinessException(BizErrorCode.BIZ_NO_PERMISSION);
        }
        //回复邀请(paas发送消息)
        replyInvite(joiner, 1, room.getChannelId());
        return true;
    }

    /**
     * 回复邀请
     *
     * @param joiner    接收用户
     * @param type      1同意 0拒绝
     * @param channelId 房间频道ID
     */
    private void replyInvite(RoomJoinsEntityDTO joiner, Integer type, String channelId) {

        String typeStr = "vrtc_connect_invite_agree";
        if (type == 0) {
            redisTemplate.opsForZSet().remove(RedisKey.INTERACT_INVITE + joiner.getRoomId(), String.valueOf(joiner.getAccountId()));
            typeStr = "vrtc_connect_invite_refused";
        }

        JSONObject msg = new JSONObject();
        msg.put("type", typeStr);
        msg.put("room_join_id", joiner.getAccountId());
        msg.put("nick_name", joiner.getNickname());
        msg.put("room_role", Integer.valueOf(joiner.getRoleName()));
        msg.put("prohibit_speak", joiner.getIsBanned());
        msg.put("kicked_out", joiner.getIsKicked());
        msg.put("device_type", joiner.getDeviceType());
        msg.put("device_status", joiner.getDeviceStatus());
        msg.put("avatar", joiner.getAvatar());

        paasService.sendMessage(channelId, msg.toJSONString());
    }

    /**
     * 邀请上麦
     *
     * @param joiner
     * @param roomId
     * @param channelId
     */
    private void sendInvite(RoomJoinsEntityDTO joiner, String roomId, String channelId) {
        String key = RedisKey.INTERACT_INVITE + roomId;
        long now = System.currentTimeMillis();
        long min = now - (RoomConstant.INVITE_VALID_TIME * 1000);
        //获取上麦中的人的数量
        Long count = redisTemplate.opsForZSet().count(key, min, Long.MAX_VALUE);
        count = count != null ? count : 0;
        //获取已经上麦的人的数量
        Integer speakerNum = getSpeakerCount(joiner);
        if (speakerNum > RoomConstant.SPEAKER_MAX_NUM) {
            throw new BusinessException(BizErrorCode.BIZ_SPEAKER_FULL);
        } else if ((count.intValue() + speakerNum) <= RoomConstant.SPEAKER_MAX_NUM) {
            //邀请数量不能大于（当前邀请数量+上麦数量）
            redisTemplate.opsForZSet().add(key, String.valueOf(joiner.getAccountId()), now);
            redisTemplate.expire(key, RoomConstant.INVITE_VALID_TIME, TimeUnit.SECONDS);

            JSONObject invitMsg = new JSONObject();
            invitMsg.put("type", "vrtc_connect_invite");
            invitMsg.put("room_join_id", joiner.getAccountId());
            invitMsg.put("nick_name", joiner.getNickname());
            invitMsg.put("room_role", Integer.valueOf(joiner.getRoleName()));
            invitMsg.put("prohibit_speak", joiner.getIsBanned());
            invitMsg.put("kicked_out", joiner.getIsKicked());
            invitMsg.put("device_type", joiner.getDeviceType());
            invitMsg.put("device_status", joiner.getDeviceStatus());
            invitMsg.put("avatar", joiner.getAvatar());
            invitMsg.put("target_id", joiner.getAccountId());

            paasService.sendMessage(channelId, invitMsg.toJSONString());
        } else {
            throw new BusinessException(BizErrorCode.BIZ_SPEAKER_INVITE_FULL);
        }

    }


}
